package com.freight.tws.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.freight.common.core.constant.DictConstants;
import com.freight.common.core.constant.WebsocketConstants;
import com.freight.common.core.exception.ServiceException;
import com.freight.common.core.utils.NoUtils;
import com.freight.common.core.utils.SecurityUtils;
import com.freight.common.core.utils.StringUtils;
import com.freight.common.core.utils.bean.BeanUtils;
import com.freight.common.security.service.TokenService;
import com.freight.common.wlhyupload.WlhyUpload;
import com.freight.tws.api.domain.*;
import com.freight.tws.api.domain.Payment;
import com.freight.tws.api.domain.PaymentOrder;
import com.freight.tws.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.freight.common.core.web.controller.BaseServiceImpl;
import com.freight.tws.mapper.PaymentMapper;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 支付Service业务层处理
 *
 * @author ruoyi
 * @date 2023-02-23
 */
@Service
public class PaymentServiceImpl extends BaseServiceImpl<PaymentMapper, Payment> implements IPaymentService {

    @Autowired
    private PaymentMapper paymentMapper;

    @Autowired
    private IPaymentOrderService paymentOrderService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IOrderGoodsService orderGoodsService;

    @Autowired
    private IDriverService driverService;

    @Autowired
    private IVehicleService vehicleService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IPtQyService ptQyService;

    @Autowired
    private ITwsNoticeService twsNoticeService;

    /**
     * 新增支付
     */
    @Override
    @Transactional
    public boolean add(Payment payment) {
        if(payment.getPaymentOrders().size() == 0) {
            throw new ServiceException("请选择订单");
        }
        payment.setDocumentNumber("ZJ" + NoUtils.randomNo()); // 支付单号(资金单号)
        payment.setApplyUserName(tokenService.getLoginUser().getSysUser().getNickName()); // 申请人
        payment.setStatus(DictConstants.PAYMENT_STATUS.YSQ.getKey());   // 状态：已申请
        payment.setIsSendToPro(DictConstants.IS_SEND_TO_PRO.WSC.getKey());  // 未上传
        boolean save = this.save(payment);

        // 保存订单
        String createBy = String.valueOf(SecurityUtils.getUserId());
        Date date = new Date();
        for (PaymentOrder paymentOrder : payment.getPaymentOrders()) {
            paymentOrder.setPaymentId(payment.getId());
            paymentOrder.setCreateBy(createBy);
            paymentOrder.setCreateTime(date);
            paymentOrder.setDelFlag(DictConstants.DELETE_BASE.OK.getKey());

            // 修改订单支付状态
            Order order = new Order();
            order.setId(paymentOrder.getOrderId());
            order.setIsPay("1");
            orderService.updateById(order);
        }
        boolean b = paymentOrderService.saveBatch(payment.getPaymentOrders());
        // 保存到业务公告消息表（包含websocket通知）
        twsNoticeService.newTwsNotice("admin", WebsocketConstants.TWS_NOTICE_TYPE.PAYMENT_APPLY.getKey(), WebsocketConstants.TWS_NOTICE_TYPE.PAYMENT_APPLY.getName());
        return save && b;
    }

    /**
     * 线下支付
     */
    @Override
    @Transactional
    public boolean payoff(Payment payment) {
        Payment pay = paymentMapper.selectById(payment.getId());
        if(StringUtils.isNull(pay)) {
            throw new ServiceException("订单不存在");
        }
        // 不是已申请状态
        if(!DictConstants.PAYMENT_STATUS.YSQ.getKey().equals(pay.getStatus())) {
            throw new ServiceException("支付状态异常");
        }
        payment.setPayUserId(SecurityUtils.getUserId());    // 支付人
        payment.setPayUserName(tokenService.getLoginUser().getSysUser().getNickName()); // 支付人
        payment.setStatus(DictConstants.PAYMENT_STATUS.YZF.getKey());   // 状态 - 已支付
        return this.updateById(payment);
    }

    /**
     * 基于资金单上传订单、司机、车辆至省平台
     */
    @Override
    @Transactional
    public boolean upload(Long id) {
        Payment payment = paymentMapper.selectById(id);
        if(payment == null) {
            throw new ServiceException("资金单不存在");
        }
        if(!DictConstants.PAYMENT_STATUS.YZF.getKey().equals(payment.getStatus())) {
            throw new ServiceException("资金单未支付");
        }
        if(DictConstants.IS_SEND_TO_PRO.YSC.getKey().equals(payment.getIsSendToPro())) {
            throw new ServiceException("该资金单已上传");
        }
        // 平台信息
        PtQy ptQy = ptQyService.lists();
        // 所有订单
        List<PaymentOrder> paymentOrders = paymentOrderService.list(new LambdaQueryWrapper<PaymentOrder>().eq(PaymentOrder::getPaymentId, id));
        List<Long> orderIds = paymentOrders.stream().map(PaymentOrder::getOrderId).collect(Collectors.toList());
        List<Order> orders = orderService.list(new LambdaQueryWrapper<Order>().in(Order::getId, orderIds));
        // 所有司机
        Set<Long> driverIds = orders.stream().map(Order::getDriverId).collect(Collectors.toSet());
        List<Driver> drivers = driverService.list(new LambdaQueryWrapper<Driver>().in(Driver::getId, driverIds));
        // 1、上传司机
        for (Driver driver : drivers) {
            if(DictConstants.IS_CERT.YRZ.getKey().equals(driver.getIsCert())) {
                if(DictConstants.IS_SEND_TO_PRO.WSC.getKey().equals(driver.getIsSendToPro())) {
                    boolean b = WlhyUpload.wlhyUpload(ptQy, driver);
                    if(b) {
                        driver.setIsSendToPro(DictConstants.IS_SEND_TO_PRO.YSC.getKey());
                        driverService.updateById(driver);
                    }
                }
            } else {
                throw new ServiceException("司机未认证");
            }
        }
        // 所有车辆（车头和挂车）
        Set<Long> vehicleIds = orders.stream().map(Order::getVehicleId).collect(Collectors.toSet());
        Set<Long> trailerVehicleIds = orders.stream().map(Order::getTrailerVehicleId).collect(Collectors.toSet());
        vehicleIds.addAll(trailerVehicleIds);
        List<Vehicle> vehicles = vehicleService.list(new LambdaQueryWrapper<Vehicle>().in(Vehicle::getId, vehicleIds));
        // 2、上传车辆
        for (Vehicle vehicle : vehicles) {
            if(DictConstants.IS_CERT.YRZ.getKey().equals(vehicle.getIsCert())) {
                if(DictConstants.IS_SEND_TO_PRO.WSC.getKey().equals(vehicle.getIsSendToPro())) {
                    boolean b = WlhyUpload.wlhyUpload(ptQy, vehicle);
                    if(b) {
                        vehicle.setIsSendToPro(DictConstants.IS_SEND_TO_PRO.YSC.getKey());
                        vehicleService.updateById(vehicle);
                    }
                }
            } else {
                throw new ServiceException("车辆未认证");
            }
        }
        // 3、上传订单
        for (Order order : orders) {
            // 订单已完成、已支付
            if(DictConstants.ORDER_STATUS.YWC.getKey().equals(order.getStatus()) && "1".equals(order.getIsPay())) {
                if(DictConstants.IS_SEND_TO_PRO.WSC.getKey().equals(order.getIsSendToPro())) {
                    List<OrderGoods> orderGoods = orderGoodsService.list(new LambdaQueryWrapper<OrderGoods>()
                            .eq(OrderGoods::getOrderId, order.getId()));
                    order.setOrderGoods(orderGoods);
                    boolean b = WlhyUpload.wlhyUpload(ptQy, order);
                    if(b) {
                        order.setIsSendToPro(DictConstants.IS_SEND_TO_PRO.YSC.getKey());
                        order.setSendToProDateTime(new Date());
                        orderService.updateById(order);
                    }
                }
            } else {
                throw new ServiceException("订单未完成或未支付");
            }
        }
        // 4、上传资金单
        PaymentUp paymentUp = new PaymentUp();
        BeanUtils.copyBeanProp(paymentUp, payment);
        paymentUp.setOrders(orders);
        boolean b = WlhyUpload.wlhyUpload(ptQy, paymentUp);
        if(b) {
            payment.setIsSendToPro(DictConstants.IS_SEND_TO_PRO.YSC.getKey());
            payment.setSendToProDateTime(new Date());
            paymentMapper.updateById(payment);
        }
        return true;
    }

}
